home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / libpr2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-22  |  32.5 KB  |  1,163 lines  |  [TEXT/MMCC]

  1. /*
  2.  * libpr2.c - a library of primitive object output routines, part 2 of 3.
  3.  *
  4.  * Author:  Eric Haines, 3D/Eye, Inc.
  5.  *
  6.  */
  7.  
  8. /*-----------------------------------------------------------------*/
  9. /* include section */
  10. /*-----------------------------------------------------------------*/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <string.h>
  16.  
  17. #include "lib.h"
  18. #include "drv.h"
  19.  
  20.  
  21. /*-----------------------------------------------------------------*/
  22. /* defines/constants section */
  23. /*-----------------------------------------------------------------*/
  24.  
  25.  
  26. /*-----------------------------------------------------------------*/
  27. /*
  28.  * Output cylinder or cone.  A cylinder is defined as having a radius and an
  29.  * axis defined by two points, which also define the top and bottom edge of the
  30.  * cylinder.  A cone is defined similarly, the difference being that the apex
  31.  * and base radii are different.  The apex radius is defined as being smaller
  32.  * than the base radius.  Note that the surface exists without endcaps.
  33.  *
  34.  * If gRT_out_format=OUTPUT_CURVES, output the cylinder/cone in format:
  35.  *     "c"
  36.  *     base.x base.y base.z base_radius
  37.  *     apex.x apex.y apex.z apex_radius
  38.  *
  39.  * If the format=OUTPUT_POLYGONS, the surface is polygonalized and output.
  40.  * (4*OUTPUT_RESOLUTION) polygons are output as rectangles by
  41.  * lib_output_polypatch.
  42.  */
  43. void
  44. lib_output_cylcone(base_pt, apex_pt, curve_format)
  45.     COORD4 base_pt, apex_pt;
  46.     int curve_format;
  47. {
  48.     MATRIX txmat;
  49.     double trans[16];
  50.     object_ptr new_object;
  51.     COORD4  axis, tempv;
  52.     double  len, cottheta, xang, yang, height;
  53.  
  54.     PLATFORM_MULTITASK();
  55.     if (gRT_out_format == OUTPUT_DELAYED) {
  56.     /* Save all the pertinent information */
  57.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  58.     if (new_object == NULL)
  59.        /* Quietly fail */
  60.        return;
  61.     new_object->object_type  = CONE_OBJ;
  62.     new_object->curve_format = curve_format;
  63.     new_object->surf_index   = gTexture_count;
  64.     if (lib_tx_active()) {
  65.         lib_get_current_tx(txmat);
  66.         new_object->tx = malloc(sizeof(MATRIX));
  67.         if (new_object->tx == NULL)
  68.            return;
  69.         else
  70.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  71.         }
  72.     else
  73.        new_object->tx = NULL;
  74.     COPY_COORD4(new_object->object_data.cone.apex_pt, apex_pt);
  75.     COPY_COORD4(new_object->object_data.cone.base_pt, base_pt);
  76.     new_object->next_object = gLib_objects;
  77.     gLib_objects = new_object;
  78.  
  79.     } else if (curve_format == OUTPUT_CURVES) {
  80.     switch (gRT_out_format) {
  81.         case OUTPUT_VIDEO:
  82.         case OUTPUT_PLG:
  83.         case OUTPUT_OBJ:
  84.         case OUTPUT_RWX:
  85.         lib_output_polygon_cylcone(base_pt, apex_pt);
  86.         break;
  87.  
  88.         case OUTPUT_NFF:
  89.         if (lib_tx_active()) {
  90.             lib_get_current_tx(txmat);
  91.             lib_tx_unwind(txmat, trans);
  92.             /* Transform the cone by modifying it's endpoints.  This
  93.                assumes uniform scaling. */
  94.             lib_transform_point(tempv, base_pt, txmat);
  95.             COPY_COORD3(base_pt, tempv)
  96.             base_pt[W] *= fabs(trans[U_SCALEX]);
  97.             lib_transform_point(tempv, apex_pt, txmat);
  98.             COPY_COORD3(apex_pt, tempv)
  99.             apex_pt[W] *= fabs(trans[U_SCALEX]);
  100.             }
  101.         fprintf(gOutfile, "c " ) ;
  102.         fprintf(gOutfile, "%g %g %g %g ",
  103.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W]);
  104.         fprintf(gOutfile, "%g %g %g %g\n",
  105.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  106.         break;
  107.  
  108.         case OUTPUT_POVRAY_10:
  109.         /*
  110.         Since POV-Ray uses infinite primitives, we will start
  111.         with a cone aligned with the z-axis (QCone_Z) and figure
  112.         out how to clip and scale it to match what we want
  113.         */
  114.         if (apex_pt[W] < base_pt[W]) {
  115.             /* Put the bigger end at the top */
  116.             COPY_COORD4(axis, base_pt);
  117.             COPY_COORD4(base_pt, apex_pt);
  118.             COPY_COORD4(apex_pt, axis);
  119.             }
  120.         /* Find the axis and axis length */
  121.         SUB3_COORD3(axis, apex_pt, base_pt);
  122.         len = lib_normalize_vector(axis);
  123.         if (len < EPSILON) {
  124.            /* Degenerate cone/cylinder */
  125.            fprintf(gOutfile, "// degenerate cone/cylinder!  Ignored...\n");
  126.            break;
  127.            }
  128.         if (ABSOLUTE(apex_pt[W] - base_pt[W]) < EPSILON) {
  129.            /* Treat this thing as a cylinder */
  130.            cottheta = len;
  131.            tab_indent();
  132.            fprintf(gOutfile, "object {\n");
  133.            tab_inc();
  134.  
  135.            tab_indent();
  136.            fprintf(gOutfile, "quadric { <1 1 0> <0 0 0> <0 0 0> -1 } // cylinder\n");
  137.  
  138.            tab_indent();
  139.            fprintf(gOutfile, "clipped_by {\n");
  140.            tab_inc();
  141.  
  142.            tab_indent();
  143.            fprintf(gOutfile, "intersection {\n");
  144.            tab_inc();
  145.  
  146.            tab_indent();
  147.            fprintf(gOutfile, "plane { <0 0 -1> 0 }\n");
  148.            tab_indent();
  149.            fprintf(gOutfile, "plane { <0 0  1> 1 }\n");
  150.  
  151.            tab_dec();
  152.            tab_indent();
  153.            fprintf(gOutfile, "} // intersection\n");
  154.  
  155.            tab_dec();
  156.            tab_indent();
  157.            fprintf(gOutfile, "} // clip\n");
  158.  
  159.            tab_indent();
  160.            fprintf(gOutfile, "scale <%g %g 1>\n", base_pt[W], base_pt[W]);
  161.            }
  162.         else {
  163.            /* Determine alignment */
  164.            cottheta = len / (apex_pt[W] - base_pt[W]);
  165.            tab_indent();
  166.            fprintf(gOutfile, "object {\n");
  167.            tab_inc();
  168.  
  169.            tab_indent();
  170.            fprintf(gOutfile, "quadric{ <1 1 -1> <0 0 0> <0 0 0> 0 } // cone\n");
  171.  
  172.            tab_indent();
  173.            fprintf(gOutfile, "clipped_by {\n");
  174.            tab_inc();
  175.  
  176.            tab_indent();
  177.            fprintf(gOutfile, "intersection {\n");
  178.            tab_inc();
  179.  
  180.            tab_indent();
  181.            fprintf(gOutfile, "plane { <0 0 -1> %g}\n", -base_pt[W]);
  182.            tab_indent();
  183.            fprintf(gOutfile, "plane { <0 0  1> %g}\n", apex_pt[W]);
  184.  
  185.            tab_dec();
  186.            tab_indent();
  187.            fprintf(gOutfile, "} // intersection\n");
  188.  
  189.            tab_dec();
  190.            tab_indent();
  191.            fprintf(gOutfile, "} // clip\n");
  192.  
  193.            tab_indent();
  194.            fprintf(gOutfile, "translate <0 0 %g>\n", -base_pt[W]);
  195.            }
  196.  
  197.         tab_indent();
  198.         fprintf(gOutfile, "scale <1 1 %g>\n", cottheta);
  199.  
  200.         len = sqrt(axis[X] * axis[X] + axis[Z] * axis[Z]);
  201.         xang = -180.0 * asin(axis[Y]) / PI;
  202.         if (len < EPSILON)
  203.           yang = 0.0;
  204.         else
  205.           yang = 180.0 * acos(axis[Z] / len) / PI;
  206.         if (axis[X] < 0)
  207.            yang = -yang;
  208.         tab_indent();
  209.         fprintf(gOutfile, "rotate <%g %g 0>\n", xang, yang);
  210.         tab_indent();
  211.         fprintf(gOutfile, "translate <%g %g %g>\n",
  212.             base_pt[X], base_pt[Y], base_pt[Z]);
  213.         if (lib_tx_active())
  214.            lib_output_tx_sequence();
  215.         if (gTexture_name != NULL) {
  216.            tab_indent();
  217.            fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  218.            }
  219.  
  220.         tab_dec();
  221.         tab_indent();
  222.         fprintf(gOutfile, "} // object\n");
  223.         fprintf(gOutfile, "\n");
  224.         break;
  225.  
  226.         case OUTPUT_POVRAY_20:
  227.         /* of course if apex_pt[W] ~= base_pt[W], could do cylinder */
  228.         tab_indent();
  229.         fprintf(gOutfile, "cone {\n");
  230.         tab_inc();
  231.  
  232.         tab_indent();
  233.         fprintf(gOutfile, "<%g, %g, %g>, %g,\n",
  234.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  235.         tab_indent();
  236.         fprintf(gOutfile, "<%g, %g, %g>, %g open\n",
  237.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W]);
  238.         if (lib_tx_active())
  239.            lib_output_tx_sequence();
  240.         if (gTexture_name != NULL) {
  241.            tab_indent();
  242.            fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  243.            }
  244.  
  245.         tab_dec();
  246.         tab_indent();
  247.         fprintf(gOutfile, "}\n");
  248.         fprintf(gOutfile, "\n");
  249.         break;
  250.  
  251.         case OUTPUT_POLYRAY:
  252.         tab_indent();
  253.         fprintf(gOutfile, "object { ");
  254.         if (base_pt[W] == apex_pt[W])
  255.            fprintf(gOutfile, "cylinder <%g, %g, %g>, <%g, %g, %g>, %g ",
  256.               base_pt[X], base_pt[Y], base_pt[Z],
  257.               apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  258.         else
  259.            fprintf(gOutfile, "cone <%g, %g, %g>, %g, <%g, %g, %g>, %g ",
  260.               base_pt[X], base_pt[Y], base_pt[Z], base_pt[W],
  261.               apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  262.         if (lib_tx_active())
  263.            lib_output_tx_sequence();
  264.         if (gTexture_name != NULL)
  265.            fprintf(gOutfile, " %s", gTexture_name);
  266.         fprintf(gOutfile, " }\n");
  267.         break;
  268.  
  269.         case OUTPUT_VIVID:
  270.         if (lib_tx_active()) {
  271.            tab_indent();
  272.            fprintf(gOutfile, "transform {\n");
  273.            lib_output_tx_sequence();
  274.            tab_indent();
  275.            fprintf(gOutfile, "}\n");
  276.            }
  277.         tab_indent();
  278.         fprintf(gOutfile, "cone {\n");
  279.         tab_inc();
  280.  
  281.         tab_indent();
  282.         fprintf(gOutfile, " base %g %g %g base_radius %g\n",
  283.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W]);
  284.         tab_indent();
  285.         fprintf(gOutfile, " apex %g %g %g apex_radius %g\n",
  286.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  287.  
  288.         tab_dec();
  289.         tab_indent();
  290.         fprintf(gOutfile, "}\n");
  291.         if (lib_tx_active())
  292.            fprintf(gOutfile, "transform_pop\n");
  293.         break;
  294.  
  295.         case OUTPUT_QRT:
  296.         fprintf(gOutfile, "BEGIN_BBOX\n");
  297.         lib_output_polygon_cylcone(base_pt, apex_pt);
  298.         fprintf(gOutfile, "END_BBOX\n");
  299.         break;
  300.  
  301.         case OUTPUT_RAYSHADE:
  302.         fprintf(gOutfile, "cone ");
  303.         if (gTexture_name != NULL)
  304.             fprintf(gOutfile, "%s ", gTexture_name);
  305.         fprintf(gOutfile, " %g %g %g %g %g %g %g %g",
  306.             base_pt[W], base_pt[X], base_pt[Y], base_pt[Z],
  307.             apex_pt[W], apex_pt[X], apex_pt[Y], apex_pt[Z]);
  308.         if (lib_tx_active())
  309.            lib_output_tx_sequence();
  310.         fprintf(gOutfile, "\n");
  311.         break;
  312.  
  313.         case OUTPUT_RTRACE:
  314.         if (lib_tx_active()) {
  315.             lib_get_current_tx(txmat);
  316.             lib_tx_unwind(txmat, trans);
  317.             /* Transform the cone by modifying it's endpoints.  This
  318.                assumes uniform scaling. */
  319.             lib_transform_point(tempv, base_pt, txmat);
  320.             COPY_COORD3(base_pt, tempv)
  321.             base_pt[W] *= fabs(trans[U_SCALEX]);
  322.             lib_transform_point(tempv, apex_pt, txmat);
  323.             COPY_COORD3(apex_pt, tempv)
  324.             apex_pt[W] *= fabs(trans[U_SCALEX]);
  325.             }
  326.         fprintf(gOutfile, "4 %d %g %g %g %g %g %g %g %g %g\n",
  327.             gTexture_count, gTexture_ior,
  328.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W],
  329.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  330.         break;
  331.  
  332.         case OUTPUT_ART:
  333.         if (base_pt[W] != apex_pt[W]) {
  334.             tab_indent();
  335.             fprintf(gOutfile, "cone {\n");
  336.             tab_inc();
  337.             if (lib_tx_active())
  338.             lib_output_tx_sequence();
  339.             tab_indent();
  340.             fprintf(gOutfile, "radius %g  center(%g, %g, %g)\n",
  341.                 base_pt[W], base_pt[X], base_pt[Y], base_pt[Z]);
  342.             tab_indent();
  343.             fprintf(gOutfile, "radius %g  center(%g, %g, %g)\n",
  344.                 apex_pt[W], apex_pt[X], apex_pt[Y], apex_pt[Z]);
  345.         } else {
  346.             tab_indent();
  347.             fprintf(gOutfile, "cylinder {\n");
  348.             tab_inc();
  349.             if (lib_tx_active())
  350.             lib_output_tx_sequence();
  351.             tab_indent();
  352.             fprintf(gOutfile, "radius %g  center(%g, %g, %g)\n",
  353.                 base_pt[W], base_pt[X], base_pt[Y], base_pt[Z]);
  354.             tab_indent();
  355.             fprintf(gOutfile, "center(%g, %g, %g)\n",
  356.                 apex_pt[X], apex_pt[Y], apex_pt[Z]);
  357.         }
  358.  
  359.         tab_dec();
  360.         tab_indent();
  361.         fprintf(gOutfile, "}\n");
  362.         fprintf(gOutfile, "\n");
  363.         break;
  364.  
  365.         case OUTPUT_RAWTRI:
  366.         case OUTPUT_DXF:
  367.         lib_output_polygon_cylcone(base_pt, apex_pt);
  368.         break;
  369.  
  370.         case OUTPUT_RIB:
  371.         /* translate and orient */
  372.         tab_indent();
  373.         fprintf(gOutfile, "TransformBegin\n");
  374.         tab_inc();
  375.         if (lib_tx_active())
  376.             lib_output_tx_sequence();
  377.  
  378.         SUB3_COORD3(axis, apex_pt, base_pt);
  379.         height= len = lib_normalize_vector(axis);
  380.         if (len < EPSILON)
  381.         {
  382.           /* Degenerate cone/cylinder */
  383.           fprintf(gOutfile, "# degenerate cone/cylinder!\n"
  384.               "Ignored...\n");
  385.           break;
  386.         }
  387.  
  388.         axis_to_z(axis, &xang, &yang);
  389.  
  390.         /* Calculate transformation from intrisic position */
  391.         tab_indent();
  392.         fprintf(gOutfile, "Translate %#g %#g %#g\n",
  393.             base_pt[X], base_pt[Y], base_pt[Z]);
  394.         tab_indent();
  395.         fprintf(gOutfile, "Rotate %#g 0 1 0\n", yang);  /* was -yang */
  396.         tab_indent();
  397.         fprintf(gOutfile, "Rotate %#g 1 0 0\n", xang);  /* was -xang */
  398.         if (ABSOLUTE(apex_pt[W] - base_pt[W]) < EPSILON)
  399.         {
  400.           /* Treat this thing as a cylinder */
  401.           tab_indent();
  402.           fprintf(gOutfile, "Cylinder [ %#g %#g %#g %#g ]\n",
  403.               apex_pt[W], 0.0, len, 360.0);
  404.         }
  405.         else
  406.         {
  407.           /* We use a hyperboloid, because a cone cannot be cut
  408.            * at the top */
  409.           tab_indent();
  410.           fprintf(gOutfile, "Hyperboloid %#g 0 0  %#g 0 %#g  360.0\n",
  411.               base_pt[W], apex_pt[W], height);
  412.         }
  413.  
  414.         tab_dec();
  415.         tab_indent();
  416.         fprintf(gOutfile, "TransformEnd\n");
  417.         break;
  418.  
  419.           }
  420.     }
  421.     else
  422.       lib_output_polygon_cylcone(base_pt, apex_pt);
  423. }
  424.  
  425.  
  426. /*-----------------------------------------------------------------*/
  427. void
  428. lib_output_disc(center, normal, iradius, oradius, curve_format)
  429.     COORD3 center, normal;
  430.     double iradius, oradius;
  431.     int curve_format;
  432. {
  433.     MATRIX txmat;
  434.     object_ptr new_object;
  435.     COORD4  axis, base, apex;
  436.     COORD3  axis_rib;
  437.     double  len, xang, yang;
  438.  
  439.     PLATFORM_MULTITASK();
  440.     if (gRT_out_format == OUTPUT_DELAYED) {
  441.     /* Save all the pertinent information */
  442.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  443.     if (new_object == NULL)
  444.         /* Quietly fail */
  445.         return;
  446.     new_object->object_type  = DISC_OBJ;
  447.     new_object->curve_format = curve_format;
  448.     new_object->surf_index   = gTexture_count;
  449.     if (lib_tx_active()) {
  450.         lib_get_current_tx(txmat);
  451.         new_object->tx = malloc(sizeof(MATRIX));
  452.         if (new_object->tx == NULL)
  453.            return;
  454.         else
  455.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  456.         }
  457.     else
  458.        new_object->tx = NULL;
  459.     COPY_COORD4(new_object->object_data.disc.center, center);
  460.     COPY_COORD4(new_object->object_data.disc.normal, normal);
  461.     new_object->object_data.disc.iradius = iradius;
  462.     new_object->object_data.disc.iradius = oradius;
  463.     new_object->next_object = gLib_objects;
  464.     gLib_objects = new_object;
  465.     } else if (curve_format == OUTPUT_CURVES) {
  466.     switch (gRT_out_format) {
  467.         case OUTPUT_VIDEO:
  468.         case OUTPUT_NFF:
  469.         case OUTPUT_PLG:
  470.         case OUTPUT_OBJ:
  471.         case OUTPUT_RWX:
  472.         case OUTPUT_VIVID:
  473.         case OUTPUT_RAYSHADE:
  474.         case OUTPUT_RAWTRI:
  475.         case OUTPUT_DXF:
  476.         lib_output_polygon_disc(center, normal, iradius, oradius);
  477.         break;
  478.  
  479.         case OUTPUT_POVRAY_10:
  480.         /* A disc is a plane intersected with either one or two
  481.          * spheres
  482.          */
  483.         COPY_COORD3(axis, normal);
  484.         len = lib_normalize_vector(axis);
  485.         tab_indent();
  486.         fprintf(gOutfile, "object {\n");
  487.         tab_inc();
  488.  
  489.         tab_indent();
  490.         fprintf(gOutfile, "plane { <0 0 1> 1 }\n");
  491.  
  492.         tab_indent();
  493.         fprintf(gOutfile, "clipped_by {\n");
  494.         tab_inc();
  495.  
  496.         if (iradius > 0.0) {
  497.             tab_indent();
  498.             fprintf(gOutfile, "intersection {\n");
  499.             tab_inc();
  500.  
  501.             tab_indent();
  502.             fprintf(gOutfile, "sphere { <0 0 0> %g inverse }\n",
  503.                 iradius);
  504.             tab_indent();
  505.             fprintf(gOutfile, "sphere { <0 0 1> %g }\n", oradius);
  506.  
  507.             tab_dec();
  508.             tab_indent();
  509.             fprintf(gOutfile, "} // intersection\n");
  510.         }
  511.         else {
  512.             tab_indent();
  513.             fprintf(gOutfile, "object { sphere { <0 0 0> %g } }\n",
  514.                 oradius);
  515.         }
  516.  
  517.         tab_dec();
  518.         tab_indent();
  519.         fprintf(gOutfile, "} // clip\n");
  520.  
  521.         len = sqrt(axis[X] * axis[X] + axis[Z] * axis[Z]);
  522.         xang = -180.0 * asin(axis[Y]) / PI;
  523.         yang = 180.0 * acos(axis[Z] / len) / PI;
  524.         if (axis[X] < 0)
  525.             yang = -yang;
  526.         tab_indent();
  527.         fprintf(gOutfile, "rotate <%g %g 0>\n", xang, yang);
  528.         tab_indent();
  529.         fprintf(gOutfile, "translate <%g %g %g>\n",
  530.             center[X], center[Y], center[Z]);
  531.         if (lib_tx_active())
  532.             lib_output_tx_sequence();
  533.  
  534.         if (gTexture_name != NULL) {
  535.             tab_indent();
  536.             fprintf(gOutfile, "texture { %s }", gTexture_name);
  537.         }
  538.  
  539.         tab_dec();
  540.         tab_indent();
  541.         fprintf(gOutfile, "} // object - disc\n");
  542.         fprintf(gOutfile, "\n");
  543.         break;
  544.  
  545.         case OUTPUT_POVRAY_20:
  546.         /* disc <center> <normalVector> radius [holeRadius] */
  547.         tab_indent();
  548.         fprintf(gOutfile, "disc { <%g, %g, %g>",
  549.             center[X], center[Y], center[Z]);
  550.         fprintf(gOutfile, " <%g, %g, %g>",
  551.             normal[X], normal[Y], normal[Z]);
  552.         fprintf(gOutfile, " %g", oradius);
  553.         if (iradius > 0.0)
  554.             fprintf(gOutfile, ", %g", iradius);
  555.         if (lib_tx_active())
  556.             lib_output_tx_sequence();
  557.         if (gTexture_name != NULL)
  558.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  559.         fprintf(gOutfile, " }\n");
  560.         fprintf(gOutfile, "\n");
  561.         break;
  562.  
  563.         case OUTPUT_POLYRAY:
  564.         tab_indent();
  565.         fprintf(gOutfile, "object { disc <%g, %g, %g>,",
  566.             center[X], center[Y], center[Z]);
  567.         fprintf(gOutfile, " <%g, %g, %g>,",
  568.             normal[X], normal[Y], normal[Z]);
  569.         if (iradius > 0.0)
  570.             fprintf(gOutfile, " %g,", iradius);
  571.         fprintf(gOutfile, " %g", oradius);
  572.         if (lib_tx_active())
  573.             lib_output_tx_sequence();
  574.         if (gTexture_name != NULL)
  575.             fprintf(gOutfile, " %s", gTexture_name);
  576.         fprintf(gOutfile, " }\n");
  577.         break;
  578.  
  579.         case OUTPUT_QRT:
  580.         fprintf(gOutfile, "BEGIN_BBOX\n");
  581.         lib_output_polygon_disc(center, normal, iradius, oradius);
  582.         fprintf(gOutfile, "END_BBOX\n");
  583.         break;
  584.  
  585.         case OUTPUT_RTRACE:
  586.         COPY_COORD3(base, center);
  587.         base[W] = iradius;
  588.         apex[X] = center[X] + normal[X] * EPSILON2;
  589.         apex[Y] = center[Y] + normal[Y] * EPSILON2;
  590.         apex[Z] = center[Z] + normal[Z] * EPSILON2;
  591.         apex[W] = oradius;
  592.         lib_output_cylcone(base, apex, curve_format);
  593.         break;
  594.  
  595.         case OUTPUT_ART:
  596.         tab_indent();
  597.         fprintf(gOutfile, "ring {\n");
  598.         tab_inc();
  599.  
  600.         if (lib_tx_active())
  601.            lib_output_tx_sequence();
  602.  
  603.         tab_indent();
  604.         fprintf(gOutfile, "center(0, 0, 0)  radius %g radius %g\n",
  605.             oradius, iradius);
  606.  
  607.         (void)lib_normalize_vector(normal);
  608.         axis_to_z(normal, &xang, &yang);
  609.  
  610.         if (ABSOLUTE(xang) > EPSILON) {
  611.             tab_indent();
  612.             fprintf(gOutfile, "rotate (%g, x)\n", xang);
  613.         }
  614.         if (ABSOLUTE(yang) > EPSILON) {
  615.             tab_indent();
  616.             fprintf(gOutfile, "rotate (%g, y)\n", yang);
  617.         }
  618.  
  619.  
  620.         if (ABSOLUTE(center[X]) > EPSILON ||
  621.             ABSOLUTE(center[Y]) > EPSILON ||
  622.             ABSOLUTE(center[Z]) > EPSILON) {
  623.             tab_indent();
  624.             fprintf(gOutfile, "translate (%g, %g, %g)\n",
  625.                 center[X], center[Y], center[Z]);
  626.         }
  627.  
  628.         tab_dec();
  629.         tab_indent();
  630.         fprintf(gOutfile, "}\n");
  631.         fprintf(gOutfile, "\n");
  632.         break;
  633.  
  634.           case OUTPUT_RIB:
  635.         if (iradius > 0)
  636.         {
  637.           /* translate and orient */
  638.           tab_indent();
  639.           fprintf(gOutfile, "TransformBegin\n");
  640.           tab_inc();
  641.           if (lib_tx_active())
  642.               lib_output_tx_sequence();
  643.  
  644.           /* Calculate transformation from intrisic position */
  645.           COPY_COORD3(axis_rib, normal);
  646.           len = lib_normalize_vector(axis_rib);
  647.           axis_to_z(axis_rib, &xang, &yang);
  648.  
  649.           tab_indent();
  650.           fprintf(gOutfile, "translate %#g %#g %#g\n",
  651.               center[X], center[Y], center[Z]);
  652.           tab_indent();
  653.           fprintf(gOutfile, "Rotate %#g 0 1 0\n", yang);  /* was -yang */
  654.           tab_indent();
  655.           fprintf(gOutfile, "Rotate %#g 1 0 0\n", xang);  /* was -xang */
  656.           tab_indent();
  657.           fprintf(gOutfile, "Disk 0 %#g 360\n", oradius);
  658.           tab_dec();
  659.           fprintf(gOutfile, "TransformEnd\n");
  660.         }
  661.         else
  662.           lib_output_polygon_disc(center, normal, iradius, oradius);
  663.         break;
  664.           }
  665.     } else {
  666.     lib_output_polygon_disc(center, normal, iradius, oradius);
  667.     }
  668. }
  669.  
  670.  
  671. /*-----------------------------------------------------------------*/
  672. static void
  673. sq_sphere_val(a1, a2, a3, n, e, u, v, P)
  674.     double a1, a2, a3, n, e, u, v;
  675.     COORD3 P;
  676. {
  677.     double cu, su, cv, sv;
  678.     double icu, isu, icv, isv;
  679.  
  680.     cu = cos(u); su = sin(u);
  681.     cv = cos(v); sv = sin(v);
  682.     icu = SGN(cu); isu = SGN(su);
  683.     icv = SGN(cv); isv = SGN(sv);
  684.     cu = fabs(cu); cv = fabs(cv);
  685.     su = fabs(su); sv = fabs(sv);
  686.     P[X] = a1 * POW(cv, n) * POW(cu, e) * icv * icu;
  687.     P[Y] = a2 * POW(cv, n) * POW(su, e) * icv * isu;
  688.     P[Z] = a3 * POW(sv, n) * isv;
  689. }
  690.  
  691. /*-----------------------------------------------------------------*/
  692. static void
  693. sq_sphere_norm(a1, a2, a3, n, e, u, v, N)
  694.     double a1, a2, a3, n, e, u, v;
  695.     COORD3 N;
  696. {
  697.     double cu, su, cv, sv;
  698.     double icu, isu, icv, isv;
  699.  
  700.     cu = cos(u); su = sin(u);
  701.     cv = cos(v); sv = sin(v);
  702.     icu = SGN(cu); isu = SGN(su);
  703.     icv = SGN(cv); isv = SGN(sv);
  704.  
  705.     /* May be some singularities in the values, lets catch them & put
  706.       a fudged normal into N */
  707.     if (e < 2 || n < 2) {
  708.     if (ABSOLUTE(cu) < 1.0e-3 || ABSOLUTE(su) < 1.0e-3 ||
  709.         ABSOLUTE(cu) < 1.0e-3 || ABSOLUTE(su) < 1.0e-3) {
  710.        SET_COORD3(N, cu*cv, su*cv, sv);
  711.        lib_normalize_vector(N);
  712.        return;
  713.     }
  714.     }
  715.  
  716.     cu = fabs(cu); cv = fabs(cv);
  717.     su = fabs(su); sv = fabs(sv);
  718.  
  719.     N[X] = a1 * POW(cv, 2-n) * POW(cu, 2-e) * icv * icu;
  720.     N[Y] = a2 * POW(cv, 2-n) * POW(su, 2-e) * icv * isu;
  721.     N[Z] = a3 * POW(sv, 2-n) * isv;
  722.     lib_normalize_vector(N);
  723. }
  724.  
  725. /*-----------------------------------------------------------------*/
  726. void
  727. lib_output_sq_sphere(center_pt, a1, a2, a3, n, e)
  728.     COORD3 center_pt;
  729.     double a1, a2, a3, n, e;
  730. {
  731.     MATRIX txmat;
  732.     object_ptr new_object;
  733.     int i, j, u_res, v_res;
  734.     double u, delta_u, v, delta_v;
  735.     COORD3 verts[4], norms[4];
  736.  
  737.     if (gRT_out_format == OUTPUT_DELAYED) {
  738.        /* Save all the pertinent information */
  739.        new_object = (object_ptr)malloc(sizeof(struct object_struct));
  740.        if (new_object == NULL)
  741.        /* Quietly fail */
  742.        return;
  743.        new_object->object_type  = SUPERQ_OBJ;
  744.        new_object->curve_format = OUTPUT_PATCHES;
  745.        new_object->surf_index   = gTexture_count;
  746.     if (lib_tx_active()) {
  747.         lib_get_current_tx(txmat);
  748.         new_object->tx = malloc(sizeof(MATRIX));
  749.         if (new_object->tx == NULL)
  750.            return;
  751.         else
  752.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  753.         }
  754.     else
  755.        new_object->tx = NULL;
  756.        COPY_COORD4(new_object->object_data.superq.center_pt, center_pt);
  757.        new_object->object_data.superq.a1 = a1;
  758.        new_object->object_data.superq.a2 = a2;
  759.        new_object->object_data.superq.a3 = a3;
  760.        new_object->object_data.superq.n  = n;
  761.        new_object->object_data.superq.e  = e;
  762.        new_object->next_object = gLib_objects;
  763.        gLib_objects = new_object;
  764.        return;
  765.     }
  766.  
  767.     u_res = 4 * gU_resolution;
  768.     v_res = 4 * gV_resolution;
  769.     delta_u = 2.0 * PI / (double)u_res;
  770.     delta_v = PI / (double)v_res;
  771.  
  772.     for (i=0,u=0.0;i<u_res;i++,u+=delta_u) {
  773.     PLATFORM_MULTITASK();
  774.     for (j=0,v=-PI/2.0;j<v_res;j++,v+=delta_v) {
  775.         if (j == 0) {
  776.         sq_sphere_val(a1, a2, a3, n, e, u, v, verts[0]);
  777.         sq_sphere_norm(a1, a2, a3, n, e, u, v, norms[0]);
  778.         sq_sphere_val(a1, a2, a3, n, e, u, v+delta_v, verts[1]);
  779.         sq_sphere_norm(a1, a2, a3, n, e, u, v+delta_v, norms[1]);
  780.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v+delta_v, verts[2]);
  781.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v+delta_v,norms[2]);
  782.         ADD3_COORD3(verts[0], verts[0], center_pt);
  783.         ADD3_COORD3(verts[1], verts[1], center_pt);
  784.         ADD3_COORD3(verts[2], verts[2], center_pt);
  785.         lib_output_polypatch(3, verts, norms);
  786.         } else if (j == v_res-1) {
  787.         sq_sphere_val(a1, a2, a3, n, e, u, v, verts[0]);
  788.         sq_sphere_norm(a1, a2, a3, n, e, u, v, norms[0]);
  789.         sq_sphere_val(a1, a2, a3, n, e, u, v+delta_v, verts[1]);
  790.         sq_sphere_norm(a1, a2, a3, n, e, u, v+delta_v, norms[1]);
  791.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v, verts[2]);
  792.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v, norms[2]);
  793.         ADD3_COORD3(verts[0], verts[0], center_pt);
  794.         ADD3_COORD3(verts[1], verts[1], center_pt);
  795.         ADD3_COORD3(verts[2], verts[2], center_pt);
  796.         lib_output_polypatch(3, verts, norms);
  797.         } else {
  798.         sq_sphere_val(a1, a2, a3, n, e, u, v, verts[0]);
  799.         sq_sphere_norm(a1, a2, a3, n, e, u, v, norms[0]);
  800.         sq_sphere_val(a1, a2, a3, n, e, u, v+delta_v, verts[1]);
  801.         sq_sphere_norm(a1, a2, a3, n, e, u, v+delta_v, norms[1]);
  802.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v+delta_v, verts[2]);
  803.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v+delta_v,norms[2]);
  804.         ADD3_COORD3(verts[0], verts[0], center_pt);
  805.         ADD3_COORD3(verts[1], verts[1], center_pt);
  806.         ADD3_COORD3(verts[2], verts[2], center_pt);
  807.         lib_output_polypatch(3, verts, norms);
  808.         COPY_COORD3(verts[1], verts[2]);
  809.         COPY_COORD3(norms[1], norms[2]);
  810.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v, verts[2]);
  811.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v, norms[2]);
  812.         ADD3_COORD3(verts[2], verts[2], center_pt);
  813.         lib_output_polypatch(3, verts, norms);
  814.         }
  815.     }
  816.     }
  817. }
  818.  
  819.  
  820. /*-----------------------------------------------------------------*/
  821. /*
  822.  * Output sphere.  A sphere is defined by a radius and center position.
  823.  *
  824.  * If format=OUTPUT_CURVES, output the sphere in format:
  825.  *     "s" center.x center.y center.z radius
  826.  *
  827.  * If the format=OUTPUT_POLYGONS, the sphere is polygonalized and output.
  828.  * The sphere is polygonalized by splitting it into 6 faces (of a cube
  829.  * projected onto the sphere) and dividing these faces by equally spaced
  830.  * great circles.  OUTPUT_RESOLUTION affects the number of great circles.
  831.  * (6*2*gU_resolution*gV_resolution) polygons are output as triangles
  832.  * using lib_output_polypatch.
  833.  */
  834. void
  835. lib_output_sphere(center_pt, curve_format)
  836.     COORD4 center_pt;
  837.     int curve_format;
  838. {
  839.     MATRIX txmat;
  840.     double trans[16];
  841.     COORD3 tempv;
  842.     object_ptr new_object;
  843.  
  844.     PLATFORM_MULTITASK();
  845.     if (gRT_out_format == OUTPUT_DELAYED) {
  846.     /* Save all the pertinent information */
  847.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  848.     if (new_object == NULL)
  849.         /* Quietly fail */
  850.         return;
  851.     new_object->object_type  = SPHERE_OBJ;
  852.     new_object->curve_format = curve_format;
  853.     new_object->surf_index   = gTexture_count;
  854.     if (lib_tx_active()) {
  855.         lib_get_current_tx(txmat);
  856.         new_object->tx = malloc(sizeof(MATRIX));
  857.         if (new_object->tx == NULL)
  858.            return;
  859.         else
  860.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  861.         }
  862.     else
  863.        new_object->tx = NULL;
  864.     COPY_COORD4(new_object->object_data.sphere.center_pt, center_pt);
  865.     new_object->next_object = gLib_objects;
  866.     gLib_objects = new_object;
  867.     }
  868.     else if (curve_format == OUTPUT_CURVES) {
  869.     switch (gRT_out_format) {
  870.         case OUTPUT_VIDEO:
  871.         case OUTPUT_PLG:
  872.         case OUTPUT_OBJ:
  873.         lib_output_polygon_sphere(center_pt);
  874.         break;
  875.  
  876.         case OUTPUT_RWX:
  877.         fprintf(gOutfile, "TransformBegin\n");
  878.         if (lib_tx_active())
  879.             lib_output_tx_sequence();
  880.         fprintf(gOutfile, "Translate %g %g %g\n",
  881.             center_pt[X], center_pt[Y], center_pt[Z]);
  882.         fprintf(gOutfile, "Sphere %g 3\n", center_pt[W]);
  883.         fprintf(gOutfile, "TransformEnd\n");
  884.         break;
  885.  
  886.         case OUTPUT_NFF:
  887.         if (lib_tx_active()) {
  888.             lib_get_current_tx(txmat);
  889.             lib_tx_unwind(txmat, trans);
  890.             /* Transform the cone by modifying it's endpoints.  This
  891.                assumes uniform scaling. */
  892.             lib_transform_point(tempv, center_pt, txmat);
  893.             COPY_COORD3(center_pt, tempv)
  894.             center_pt[W] *= fabs(trans[U_SCALEX]);
  895.             }
  896.         fprintf(gOutfile, "s %g %g %g %g\n",
  897.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  898.         break;
  899.  
  900.         case OUTPUT_POVRAY_10:
  901.         tab_indent();
  902.         fprintf(gOutfile, "object { sphere { <%g %g %g> %g } ",
  903.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  904.         if (lib_tx_active())
  905.             lib_output_tx_sequence();
  906.         if (gTexture_name != NULL)
  907.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  908.         fprintf(gOutfile, " }\n");
  909.         fprintf(gOutfile, "\n");
  910.         break;
  911.  
  912.         case OUTPUT_POVRAY_20:
  913.         tab_indent();
  914.         fprintf(gOutfile, "sphere { <%g, %g, %g>, %g ",
  915.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  916.         if (lib_tx_active())
  917.             lib_output_tx_sequence();
  918.         if (gTexture_name != NULL)
  919.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  920.         fprintf(gOutfile, " }\n");
  921.         fprintf(gOutfile, "\n");
  922.         break;
  923.  
  924.         case OUTPUT_POLYRAY:
  925.         tab_indent();
  926.         fprintf(gOutfile, "object { sphere <%g, %g, %g>, %g ",
  927.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  928.         if (lib_tx_active())
  929.             lib_output_tx_sequence();
  930.         if (gTexture_name != NULL)
  931.             fprintf(gOutfile, " %s", gTexture_name);
  932.         fprintf(gOutfile, " }\n");
  933.         break;
  934.  
  935.         case OUTPUT_VIVID:
  936.         if (lib_tx_active()) {
  937.            tab_indent();
  938.            fprintf(gOutfile, "transform {\n");
  939.            lib_output_tx_sequence();
  940.            tab_indent();
  941.            fprintf(gOutfile, "}\n");
  942.            }
  943.         tab_indent();
  944.         fprintf(gOutfile, "sphere { center %g %g %g radius %g }\n",
  945.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  946.         fprintf(gOutfile, "\n");
  947.         if (lib_tx_active())
  948.            fprintf(gOutfile, "transform_pop\n");
  949.         break;
  950.  
  951.         case OUTPUT_QRT:
  952.         if (lib_tx_active()) {
  953.             lib_get_current_tx(txmat);
  954.             lib_tx_unwind(txmat, trans);
  955.             /* Transform the cone by modifying it's endpoints.  This
  956.                assumes uniform scaling. */
  957.             lib_transform_point(tempv, center_pt, txmat);
  958.             COPY_COORD3(center_pt, tempv)
  959.             center_pt[W] *= fabs(trans[U_SCALEX]);
  960.             }
  961.         tab_indent();
  962.         fprintf(gOutfile, "sphere ( loc = (%g, %g, %g), radius = %g )\n",
  963.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  964.         break;
  965.  
  966.         case OUTPUT_RAYSHADE:
  967.         fprintf(gOutfile, "sphere ");
  968.         if (gTexture_name != NULL)
  969.             fprintf(gOutfile, "%s ", gTexture_name);
  970.         fprintf(gOutfile, " %g %g %g %g ",
  971.             center_pt[W], center_pt[X], center_pt[Y], center_pt[Z]);
  972.         if (lib_tx_active())
  973.             lib_output_tx_sequence();
  974.         fprintf(gOutfile, "\n");
  975.         break;
  976.  
  977.         case OUTPUT_RTRACE:
  978.         if (lib_tx_active()) {
  979.             lib_get_current_tx(txmat);
  980.             lib_tx_unwind(txmat, trans);
  981.             /* Transform the cone by modifying it's endpoints.  This
  982.                assumes uniform scaling. */
  983.             lib_transform_point(tempv, center_pt, txmat);
  984.             COPY_COORD3(center_pt, tempv)
  985.             center_pt[W] *= fabs(trans[U_SCALEX]);
  986.             }
  987.         fprintf(gOutfile, "1 %d %g %g %g %g %g\n",
  988.             gTexture_count, gTexture_ior,
  989.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  990.         break;
  991.  
  992.         case OUTPUT_ART:
  993.         tab_indent();
  994.         fprintf(gOutfile, "sphere {\n");
  995.         tab_inc();
  996.         if (lib_tx_active())
  997.             lib_output_tx_sequence();
  998.  
  999.         tab_indent();
  1000.         fprintf(gOutfile, "radius %g\n", center_pt[W]);
  1001.         tab_indent();
  1002.         fprintf(gOutfile, "center(%g, %g, %g)\n",
  1003.             center_pt[X], center_pt[Y], center_pt[Z]);
  1004.  
  1005.         tab_dec();
  1006.         tab_indent();
  1007.         fprintf(gOutfile, "}\n");
  1008.         fprintf(gOutfile, "\n");
  1009.         break;
  1010.  
  1011.         case OUTPUT_RAWTRI:
  1012.         case OUTPUT_DXF:
  1013.         lib_output_polygon_sphere(center_pt);
  1014.         break;
  1015.           case OUTPUT_RIB:
  1016.         tab_indent();
  1017.         fprintf(gOutfile, "TransformBegin\n");
  1018.         tab_inc();
  1019.         if (lib_tx_active())
  1020.            lib_output_tx_sequence();
  1021.         tab_indent();
  1022.         fprintf(gOutfile, "Translate %#g %#g %#g\n",
  1023.             center_pt[X], center_pt[Y], center_pt[Z]);
  1024.         tab_indent();
  1025.         fprintf(gOutfile, "Sphere %#g %#g %#g 360\n",
  1026.             center_pt[W], -center_pt[W], center_pt[W]);
  1027.         tab_dec();
  1028.         tab_indent();
  1029.         fprintf(gOutfile, "TransformEnd\n");
  1030.         break;
  1031.     }
  1032.     } else {
  1033.     lib_output_polygon_sphere(center_pt);
  1034.     }
  1035. }
  1036.  
  1037.  
  1038.  
  1039. /*-----------------------------------------------------------------*/
  1040. /* Output box.  A box is defined by a diagonally opposite corners. */
  1041. void
  1042. lib_output_box(p1, p2)
  1043.     COORD3 p1, p2;
  1044. {
  1045.     MATRIX txmat;
  1046.     object_ptr new_object;
  1047.  
  1048.     PLATFORM_MULTITASK();
  1049.     if (gRT_out_format == OUTPUT_DELAYED) {
  1050.     /* Save all the pertinent information */
  1051.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  1052.     if (new_object == NULL)
  1053.         /* Quietly fail */
  1054.         return;
  1055.     new_object->object_type  = BOX_OBJ;
  1056.     new_object->curve_format = OUTPUT_PATCHES;
  1057.     new_object->surf_index   = gTexture_count;
  1058.     if (lib_tx_active()) {
  1059.         lib_get_current_tx(txmat);
  1060.         new_object->tx = malloc(sizeof(MATRIX));
  1061.         if (new_object->tx == NULL)
  1062.            return;
  1063.         else
  1064.            memcpy(new_object->tx, txmat, sizeof(MATRIX));
  1065.         }
  1066.     else
  1067.        new_object->tx = NULL;
  1068.     COPY_COORD3(new_object->object_data.box.point1, p1);
  1069.     COPY_COORD3(new_object->object_data.box.point2, p2);
  1070.     new_object->next_object = gLib_objects;
  1071.     gLib_objects = new_object;
  1072.     } else {
  1073.     switch (gRT_out_format) {
  1074.         case OUTPUT_VIDEO:
  1075.         case OUTPUT_NFF:
  1076.         case OUTPUT_VIVID:
  1077.         case OUTPUT_PLG:
  1078.         case OUTPUT_OBJ:
  1079.         case OUTPUT_RAWTRI:
  1080.         case OUTPUT_RIB:
  1081.         case OUTPUT_DXF:
  1082.         case OUTPUT_RWX:
  1083.         lib_output_polygon_box(p1, p2);
  1084.         break;
  1085.  
  1086.         case OUTPUT_POVRAY_10:
  1087.         tab_indent();
  1088.         fprintf(gOutfile, "object { box { <%g %g %g> <%g %g %g> }",
  1089.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  1090.         if (lib_tx_active())
  1091.            lib_output_tx_sequence();
  1092.         if (gTexture_name != NULL)
  1093.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  1094.         fprintf(gOutfile, " }\n");
  1095.         fprintf(gOutfile, "\n");
  1096.         break;
  1097.  
  1098.         case OUTPUT_POVRAY_20:
  1099.         tab_indent();
  1100.         fprintf(gOutfile, "box { <%g, %g, %g>, <%g, %g, %g>  ",
  1101.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  1102.         if (lib_tx_active())
  1103.            lib_output_tx_sequence();
  1104.         if (gTexture_name != NULL)
  1105.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  1106.         fprintf(gOutfile, " }\n");
  1107.         fprintf(gOutfile, "\n");
  1108.         break;
  1109.  
  1110.         case OUTPUT_POLYRAY:
  1111.         fprintf(gOutfile, "object { box <%g, %g, %g>, <%g, %g, %g>",
  1112.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  1113.         if (lib_tx_active())
  1114.            lib_output_tx_sequence();
  1115.         if (gTexture_name != NULL)
  1116.             fprintf(gOutfile, " %s", gTexture_name);
  1117.         fprintf(gOutfile, " }\n");
  1118.         break;
  1119.  
  1120.         case OUTPUT_QRT:
  1121.         fprintf(gOutfile, "BEGIN_BBOX\n");
  1122.         lib_output_polygon_box(p1, p2);
  1123.         fprintf(gOutfile, "END_BBOX\n");
  1124.         break;
  1125.  
  1126.         case OUTPUT_RAYSHADE:
  1127.         fprintf(gOutfile, "box ");
  1128.         if (gTexture_name != NULL)
  1129.             fprintf(gOutfile, "%s ", gTexture_name);
  1130.         fprintf(gOutfile, " %g %g %g %g %g %g",
  1131.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  1132.         if (lib_tx_active())
  1133.            lib_output_tx_sequence();
  1134.         fprintf(gOutfile, "\n");
  1135.         break;
  1136.  
  1137.         case OUTPUT_ART:
  1138.         tab_indent();
  1139.         fprintf(gOutfile, "box {\n");
  1140.         if (lib_tx_active())
  1141.            lib_output_tx_sequence();
  1142.         fprintf(gOutfile, " vertex(%g, %g, %g)\n",
  1143.             p1[X], p1[Y], p1[Z]);
  1144.         fprintf(gOutfile, " vertex(%g, %g, %g) }\n",
  1145.             p2[X], p2[Y], p2[Z]);
  1146.         fprintf(gOutfile, "\n");
  1147.         break;
  1148.  
  1149.         case OUTPUT_RTRACE:
  1150.         if (lib_tx_active())
  1151.             lib_output_polygon_box(p1, p2);
  1152.         else
  1153.            fprintf(gOutfile, "2 %d %g %g %g %g %g %g %g\n",
  1154.                gTexture_count, gTexture_ior,
  1155.                (p1[X] + p2[X]) / 2.0,
  1156.                (p1[Y] + p2[Y]) / 2.0,
  1157.                (p1[Z] + p2[Z]) / 2.0,
  1158.                p2[X] - p1[X], p2[Y] - p1[Y], p2[Z] - p1[Z]);
  1159.         break;
  1160.     }
  1161.     }
  1162. }
  1163.